package com.quandou.base.security;

import com.quandou.base.properties.SecurityProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.session.data.redis.config.ConfigureRedisAction;

@Configuration
@EnableConfigurationProperties(SecurityProperties.class)
public class CoreSecurityConfig extends WebSecurityConfigurerAdapter {

    private SecurityProperties securityProperties;
    private AuthorizeConfigManager authorizeConfigManager;

    public CoreSecurityConfig(SecurityProperties securityProperties, AuthorizeConfigManager authorizeConfigManager) {
        this.securityProperties = securityProperties;
        this.authorizeConfigManager = authorizeConfigManager;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        String[] permitUrls = securityProperties.getPermitUrls();
        if (null != permitUrls && permitUrls.length > 0) {
            http.authorizeRequests().antMatchers(permitUrls).permitAll();
        }

        http.cors().and().csrf().disable();

        http.logout()
                .addLogoutHandler(coreLogoutHandler())
                .logoutSuccessHandler(coreLogoutHandler());

        http.exceptionHandling()
                .accessDeniedHandler(coreAccessDeniedHandler())
                .authenticationEntryPoint(coreAccessDeniedHandler());
        http.addFilterAt(coreAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);

        authorizeConfigManager.config(http);
    }

    private CoreAuthenticationFilter coreAuthenticationFilter() throws Exception {
        CoreAuthenticationFilter filter = new CoreAuthenticationFilter();
        filter.setAuthenticationSuccessHandler(coreAuthenticationHandler());
        filter.setAuthenticationFailureHandler(coreAuthenticationHandler());
        filter.setAuthenticationManager(authenticationManager());
        return filter;
    }

    @Bean
    public CoreAuthenticationHandler coreAuthenticationHandler() {
        return new CoreAuthenticationHandler();
    }

    @Bean
    public CoreLogoutHandler coreLogoutHandler() {
        return new CoreLogoutHandler();
    }

    @Bean
    public CoreAccessDeniedHandler coreAccessDeniedHandler() {
        return new CoreAccessDeniedHandler();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    @Bean
    public static ConfigureRedisAction configureRedisAction() {
        return ConfigureRedisAction.NO_OP;
    }
}
